import type { ApiFuncData, RequestFunction } from '@/apis/types';
import type { RowKey } from '@ykst/components';
import { type ModalFuncProps } from 'ant-design-vue';
import { ref } from 'vue';
import { useAppNotification } from '../feedback/useAppNotification';
import { useAppFeedback } from '../feedback/useAppFeedback';
// const { modal: Modal } = App.useApp();

// 去除不为undefined的字段
type NoNullableKey<D, T extends keyof D> = Omit<ApiFuncData, T> & {
  [key in T]: NonNullable<D[T]>;
};

type ActionType = boolean | string;

export type useFormBeforeSubmit<D, FD = D> = (
  value: NoNullableKey<ApiFuncData<FD>, 'data'>,
  edit: boolean,
) => ApiFuncData<D> | Promise<ApiFuncData<D>>;
export type useFormSubmitFunc<D> = RequestFunction<any, D>;

/**
 * 通用的表单编辑和新增提交函数
 * @param { RequestFunction<any, D> } requestFunc 表单提交函数
 * @param { useFormBeforeSubmit<D, FD > } [beforeSubmit] 表单提交函数运行之前的函数，可以在这里处理请求参数
 * @param { string } [actionTitle] 操作的标题，如：设备停机记录
 *
 * @description 泛型说明
 * - 泛型D： requestFunc的ApiFuncData.data类型，
 * - 泛型FD： 表单的data类型（FormData），默认和D一样，大部分情况FD和D不一样，
 */
export function useFormSubmit<D = any, FD = D>(
  requestFunc: useFormSubmitFunc<D>,
  beforeSubmit?: useFormBeforeSubmit<D, FD> | string,
  actionTitle: string = '',
) {
  const _actionTitle = actionTitle || (typeof beforeSubmit === 'string' ? beforeSubmit : '');
  const { modal } = useAppFeedback();
  const { notification } = useAppNotification();
  // 请求加载
  const loading = ref(false);

  // 表单提交
  async function submitRequest(data: ApiFuncData<D>, action?: ActionType) {
    loading.value = true;
    try {
      const res = await requestFunc(data);
      loading.value = false;
      action &&
        notification.fastSuccess({ message: _actionTitle || '提示', description: action + '成功' });
      return res;
    } catch (e) {
      loading.value = false;
      // 已经在请求拦截中统一处理请求报错信息
      // action && notification.fastError({ message: `${action}失败` });
      return Promise.reject(e);
    }
  }

  /**
   * 新增提交 post
   * @param { FD } data 修改提交的data参数，FD默认和D一样
   * @param { ActionType } action 操作名称用来显示请求成功还是失败的提示，默认新增，如果为false,不显示提示信息
   */
  async function addSubmit(data: FD, action?: ActionType) {
    const _data = { data, method: 'post' };
    if (typeof beforeSubmit === 'function') {
      return await submitRequest(
        await beforeSubmit(_data as NoNullableKey<ApiFuncData<FD>, 'data'>, false),
      );
    }
    if (action === true || action === undefined) {
      action = '新增' + _actionTitle;
    }
    return await submitRequest(_data as ApiFuncData<D>, action);
  }

  /**
   * 编辑提交 put
   * @param { FD } data 修改提交的data参数，FD默认和D一样
   * @param { RowKey  } [id] 修改记录的id，拼接到路径后面
   * @param { ActionType } action 操作名称用来显示请求成功还是失败的提示，默认新增，如果为false,不显示提示信息
   */
  async function editSubmit(data: FD, id?: RowKey, action?: ActionType) {
    let _data: ApiFuncData = { data, params: id, method: 'put' };

    if (typeof beforeSubmit === 'function') {
      _data = await beforeSubmit(_data as NoNullableKey<ApiFuncData<FD>, 'data'>, true);
    }
    if (action === true || action === undefined) {
      action = '编辑' + _actionTitle;
    }
    return await submitRequest(_data, action);
  }

  const confirmLoading = ref(false);
  /**
   * 弹框确认后编辑提交 put
   * @param  { FD } data 修改提交的data参数，FD默认和D一样
   * @param  { ModalFuncProps } [config]  Modal.confirm 的参数
   * @param { RowKey } [id] 修改记录的id，拼接到路径后面
   * @param { ActionType } action 操作名称用来显示请求成功还是失败的提示，默认新增，如果为false,不显示提示信息
   */
  async function onConfirmSubmit(
    data: FD,
    config?: ModalFuncProps,
    id?: RowKey,
    action?: ActionType,
  ) {
    return new Promise(resolve =>
      modal.confirm({
        title: '确定修改？',
        okText: '确定',
        okType: 'primary',
        cancelText: '取消',
        centered: true,
        ...config,
        async onOk() {
          confirmLoading.value = true;
          const res = await editSubmit(data, id, action);
          confirmLoading.value = false;
          resolve(res);
        },
      }),
    );
  }

  const disableLoading = ref(false);
  /**
   * 批量禁用
   * @param data 修改提交的data参数，FD默认和D一样
   */
  function onBatchDisable(data: FD) {
    return new Promise(resolve =>
      modal.confirm({
        title: '确定禁用？',
        okText: '禁用',
        okType: 'danger',
        cancelText: '取消',
        centered: true,
        async onOk() {
          disableLoading.value = true;
          const res = await editSubmit(data, undefined, '禁用' + _actionTitle);
          disableLoading.value = false;
          resolve(res);
        },
      }),
    );
  }

  const enableLoading = ref(false);
  /**
   * 批量启用
   * @param data 修改提交的data参数，FD默认和D一样
   */
  function onBatchEnable(data: FD) {
    return new Promise(resolve =>
      modal.confirm({
        title: '确定启用？',
        okText: '启用',
        okType: 'primary',
        cancelText: '取消',
        centered: true,
        async onOk() {
          enableLoading.value = true;
          const res = await editSubmit(data, undefined, '启用' + _actionTitle);
          enableLoading.value = false;
          resolve(res);
        },
      }),
    );
  }

  return {
    editSubmit,
    addSubmit,
    onConfirmSubmit,
    onBatchEnable,
    onBatchDisable,
    loading,
    disableLoading,
    enableLoading,
  };
}
